#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <math.h>


                        //We use msg in chars to pass the info.
#define SEQLENGTH 8		//sequence number length in bytes
#define IDLENGTH 1		//Network id length in bytes
#define FSIZE 1024		//Frame size in bytes
#define PORT 7654		//Port number of the reciever
#define SENDNUM 1000

//return current timestamp as a long int 
long timestamp() {
	time_t ltime;
	struct timeval ts;
	long timeinms;
	ltime = time(NULL);
	gettimeofday(&ts, NULL);
	timeinms = ts.tv_sec * 1000000 + ts.tv_usec;
//	printf("Here is the time in timeinms: %ld\n", timeinms);
	return timeinms;
}

//build a packet to send
void buildframe(char *buf, int seq) {
	snprintf(buf, 11, "%01d%08d", cid, seq);
	buf = buf + IDLENGTH + SEQLENGTH;
	sprintf(buf, "%ld", timestamp());
}

//delay 1/R seconds, R is the rate packets/second 
void delay(int rate) {
	float rateF, delaynsec;
	int delaysec;
	struct timespec tmReq = { 0 }, tmRem = { 0 };
	rateF = (float) rate;
	delaysec = (int) 1 / rateF;
	tmReq.tv_sec = delaysec;
	delaynsec = (float) 1 / rate - delaysec;
	tmReq.tv_nsec = delaynsec * 1000000000L;
	nanosleep(&tmReq, &tmRem);
}

//delay -log(random)/R second, random is a random number between 0 and 1
void delay2(int rate){
	float rateF, delaynsec, time;
	int delaysec;
	struct timespec tmReq = { 0 }, tmRem = { 0 };
	float ran;
	while((ran=(float)rand()/(float)RAND_MAX)==0);
	rateF = (float) rate;
//	time = -(float)log(ran)/rateF;
	delaysec = (int) time;
	tmReq.tv_sec = delaysec;
	delaynsec = time - delaysec;
	tmReq.tv_nsec = delaynsec * 1000000000L;
	nanosleep(&tmReq, &tmRem);
}

int main(int argc, char *argv[]) {
	int sock, seqnum, rate, bytes_sent, buffer_length,i, sent, cid;
	struct sockaddr_in sa;
	char buffer[FSIZE];
	sent =0;

	if (argc != 3) {
		printf("Format: source id rate(packets per second)");
		exit(EXIT_FAILURE);
	}
    cid = atoi(argv[1]);
	rate = atoi(argv[2]);
	seqnum = 0;

    printf("%d\n",rate);
	
	sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (-1 == sock) /* if socket failed to initialize, exit */
	{
		printf("Error Creating Socket");
		exit(EXIT_FAILURE);
	}

	memset(&sa, 0, sizeof(sa));
	sa.sin_family = AF_INET;
	sa.sin_addr.s_addr = INADDR_ANY;
	sa.sin_port = htons(PORT);

	for (i=0;i<SENDNUM;i++) {
		delay(rate);
		buildframe(buffer, seqnum);

		//printf("here is the buffer %s\n", buffer);
		buffer_length = FSIZE;

		seqnum++;
		bytes_sent = sendto(sock, buffer, buffer_length, 0,
				(struct sockaddr*) &sa, sizeof(struct sockaddr_in));
		if (bytes_sent < 0)
			printf("Error sending packet: %s\n", strerror(errno));
		sent++;
	}
	close(sock); /* close the socket */
	return 0;
}
